package ru.zombator.taskman.core.domain;

import java.io.Serializable;
import java.sql.Date;
import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Штамп времени &mdash; дата в формате ISO (<code>20111231</code>)
 * 
 * @author nvamelichev
 * 
 */
public class Datestamp implements Serializable {
	private static final long serialVersionUID = 1L;
	
	/**
	 * год
	 */
	private int year;
	/**
	 * месяц
	 */
	private byte month;
	/**
	 * день
	 */
	private byte day;

	private void tryConstruct(int year, byte month, byte day)
			throws IllegalArgumentException {
		Calendar cal = Calendar.getInstance();
		cal.setLenient(false);
		try {
			cal.set(year, month - 1, day);
		} catch (Exception ex) {
			throw new IllegalArgumentException("incorrect date");
		}

		this.year = year;
		this.month = month;
		this.day = day;
	}

    /**
     * Создает штамп даты по SQL-дате
     * 
     * @param sqlDate
     *            - SQL-дата
     * @throws IllegalArgumentException
     *             некорректная дата
     */
	@SuppressWarnings("deprecation")
    public Datestamp(Date sqlDate) throws IllegalArgumentException {
        this(sqlDate.getYear(), (byte) (sqlDate.getMonth() + 1),
                (byte) sqlDate.getDay());
    }
	
	/**
	 * Создает штамп даты по строке в формате <code>"20111231"</code>
	 * 
	 * @param isoString
	 *            - строка с датой
	 * @throws IllegalArgumentException
	 *             некорректная строка
	 */
	public Datestamp(String isoString) throws IllegalArgumentException {
		final Matcher TIMESTAMP_MATCHER = Pattern.compile(
				"(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)").matcher(isoString);
		if (!TIMESTAMP_MATCHER.matches())
			throw new IllegalArgumentException("not an iso-style date");

		int year;
		byte month;
		byte day;
		try {
			year = Integer.parseInt(TIMESTAMP_MATCHER.group(1));
			month = Byte.parseByte(TIMESTAMP_MATCHER.group(2));
			day = Byte.parseByte(TIMESTAMP_MATCHER.group(3));
		} catch (NumberFormatException nfe) {
			throw new IllegalArgumentException("bad number format");
		}

		tryConstruct(year, month, day);
	}

	/**
	 * Создает штамп даты по значениям года, месяца и дня.
	 * 
	 * @param year
	 *            - год
	 * @param month
	 *            - месяц
	 * @param day
	 *            - день
	 * @throws IllegalArgumentException
	 *             неверные значения полей
	 */
	public Datestamp(int year, byte month, byte day)
			throws IllegalArgumentException {
		tryConstruct(year, month, day);
	}

	public String toString() {
		return String.format("%02d%02d%02d", year, month, day);
	}

	/**
	 * @return дата в виде SQL Date
	 */
	@SuppressWarnings("deprecation")
    public Date asSqlDate() {
        return new Date(year, month - 1, day);
    }
}
